iT邦幫忙

2022 iThome 鐵人賽

DAY 5
1
自我挑戰組

在30天利用HTML & CSS & JavaScript完成Side Project實作系列 第 5

Day 5 Side Project : Blurry Loading 模糊加載

  • 分享至 

  • xImage
  •  


今天要來做的是圖片模糊加載,圖片一開始是很模糊的,隨著加載率從0%~100%的過程中,會越來越清楚,最後進入焦點,而加載文字的部分則會慢慢淡出


事前準備

1.一張你喜歡的圖片,要做為背景用


運用知識點羅列

  • CSS
知識點 使用說明
Background 背景 設定背景圖片格式
Filter濾鏡效果 圖片的模糊處理
calc() 計算函數 計算模糊範圍
  • JS
知識點 使用說明
querySelector() 獲取HTML元素
setInterval() / clearInterval() 抓取加載%數的範圍
innerText 把加載文字渲染在畫面上

流程講解

  • HTML
 <div class="bg"></div>
    <!-- 加載文字-->
    <div class="loading-text">0%</div>
  • CSS
    背景
div.bg {
/* <background-image> <background-repeat> <background-position> / <background-size>*/

  background: url("...") no-repeat 50% 50% / cover;
  position: absolute;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  z-index: -1;
  filter: blur(30px);
}

background是有關背景圖片的各個屬性集合,關於background的順序並沒有一個很明確的標準,可以參考stackoverflow上的這篇文章

background-position設為50% 50%也等於center center,如果兩個值都一樣,可以只寫一個
background-positionbackground-size之間會用『/』去區隔彼此

這裡主要就是設定背景圖片的大小、位子...,並利用filter:blur(PX)去做模糊效果,數字越大越模糊,如果沒有填入,預設是0

加載文字

.loading-text {
  font-size: 50px;
  color: white;
}

若以上都設定好呈現如下,好像沒有戴上眼鏡的世界一樣模糊
不過我們會看到周圍會有一圈白邊,如果我想要讓白邊的範圍不要那麼大,稍微內縮,可以怎麼做呢??
https://ithelp.ithome.com.tw/upload/images/20220911/20149362DprI0sJ13D.png

以下程式碼只擷取有修改過的部分,我們為了把白邊範圍內縮一點,所以把top和left設定為"負數",所以它就會往視窗上方以及左方移動,這點應該沒有問題,不過如果只設這樣並不夠,那我右邊和下面的白框還是沒有內縮啊~該怎麼辦呢?

其實有兩種解法,第一種就是很直覺的把rightbottom設為-30px,不過還有更精簡的寫法,就是底下這種寫法

calc取自英文calculator的前面四個字,意思是計算,所以 calc(mathematical expression)通常拿來做數值的運算,而且運算的數值"不需要"相同單位,我可以「 px + % 」或是「 % - px - em」等,彈性相當大,不過若運算子中間沒有空格格開(如:「 px+% 」),整個效果就會不見,這也是我在實作的過程意外發現的bug

div.bg {
  top: -30px;
  left: -30px;
  width: calc(100vw + 60px);
  height: calc(100vh + 60px);
}


  • JS
    抓取加載%數的範圍
let loadText = document.querySelector(".loading-text");
let bg = document.querySelector(".bg");

let load = 0;
let int = setInterval(blurring, 30); //每30毫秒執行一次blurring這個函式
function blurring() {
  load++;
  console.log(load);
  
    //記得clearInterval()
    if (load > 99) {
      clearInterval(int);
    }
}

你可以試著把clearInterval()註解看看,打開Dev tool就會看到一串無限的數字再跑 @ @ ,所以務必要記得clearInterval()!!這樣一來它的範圍只會被我們限縮在0~100,而我們要利用這個結論去讓加載文字可以從0%~100%去跑
https://ithelp.ithome.com.tw/upload/images/20220911/20149362fcYvFyo1yE.png

繼續加上下面這一段,我們要把剛剛load的數字渲染到畫面上

 loadText.innerText = `${load}%`;

呈現會如下圖,算是完成1/3了

我們在最一開始的完成版看到,隨著加載率的上升,除了圖片越來越清楚外,%數則會慢慢淡出,接下來我們要來實作%數慢慢淡出這一段

這可以說是此賽pjoject的重頭戲,參考了sackoverflow上的一篇文章來完成,它是一個要把一個數字範圍應設到另一個數字範圍的function,恩..聽不懂沒關係,直接看底下程式碼更清楚,這用法也是我第一次看到,先附上stackoverflow的文章map a range of numbers to another range of numbers

%數的淡出

0% ➔ opacity:1;
100% ➔ opacity:0;
利用opacity去控制

loadText.style.opacity = scale(load, 0, 100, 1, 0); //加載數字(load)0-100的透明度為1-0

  // 以下取自stackoverflow
  function scale(number, inMin, inMax, outMin, outMax) {
    return ((number - inMin) * (outMax - outMin)) / (inMax - inMin) + outMin;
  }

設定好後,呈現如下,我們讓數字慢慢淡出了,完成2/3了ヽ(✿゚▽゚)ノ

圖片的模糊程度
跟%數的淡出其實是同理

 bg.style.filter = `blur(${scale(load, 0, 100, 30, 0)}px)`;//加載數字(load)0-100的圖片的模糊程度為blur(30px)➔blur(0px)

若以上都設定好,就全部完成啦~

在此附上codepen連結 https://codepen.io/hangineer/pen/zYjqMMj

另外也可以不使用stackoverflow的那個function,有更簡潔的方法
https://ithelp.ithome.com.tw/upload/images/20220911/201493622xIMHC0ckY.png
圖片取自50 Projects In 50 Days - HTML, CSS & JavaScript FAQ


summary 總結

本篇用到了calc()setInterval()clearInterval()、數字範圍變化的function等,各個知識點的釐清很重要,另外也在底下補充了一些常混淆的觀念

[補充]
談談 JavaScript 的 setTimeout 與 setInterval
JavaScript innerHTML 與 innerText 的差異
關於javaScript的Expression和Statement

若有解說不夠詳盡或是錯誤歡迎指教,感激不盡!明天見/images/emoticon/emoticon07.gif


參考資料

50 Projects In 50 Days - HTML, CSS & JavaScript
CSS Background-position
w3School CSS filter
map a range of numbers to another range of numbers


上一篇
Day 4 Side Project : Rotating Navigation 旋轉的導覽列
下一篇
Day 6 Side Project : Scroll Animation 滾動動畫
系列文
在30天利用HTML & CSS & JavaScript完成Side Project實作30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
hannnahTW
iT邦新手 3 級 ‧ 2022-09-14 12:11:47

[補充]
設在背景圖片中的 filter: blur(30px); 是可以省略的
因為後來透過以下這段javaScript去控制了

// 圖片的模糊程度
  bg.style.filter = `blur(${scale(load, 0, 100, 30, 0)}px
  
  function scale(number, inMin, inMax, outMin, outMax) {
    return ((number - inMin) * (outMax - outMin)) / (inMax - inMin) + outMin;
  }

我要留言

立即登入留言